package com.example.apidocserver.infrastructure.util.document;

import com.alibaba.druid.util.StringUtils;
import com.example.apidocserver.domain.document.entity.ApiInfo;
import com.example.apidocserver.domain.document.entity.ApiParam;
import com.example.apidocserver.domain.document.entity.ApiParamField;
import com.example.apidocserver.domain.document.entity.ApiParamHis;
import com.example.apidocserver.infrastructure.constants.SystemConstants;
import com.example.apidocserver.interfaces.vo.ApiInfoAllVo;
import com.example.apidocserver.interfaces.vo.ApiParamDescVo;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;

import static com.example.apidocserver.infrastructure.util.document.EntityToWord.FIELD_TITLE_STR;


/**
 * 实体对象转markdown工具
 *
 * @author xyqlg
 */
public class EntityToMarkdown {
    /**
     * 设置接口信息
     *
     * @param sb      文档信息
     * @param apiInfo 接口信息
     */
    public static void setApiInfo(StringBuilder sb, ApiInfo apiInfo, int startTitle) {
        setTitle(sb, apiInfo.getApiName(), startTitle);
        setTitle(sb, "接口信息", startTitle + 1);
        sb.append(apiInfo.getApiDesc()).append("\n");
        setTitle(sb, "接口信息", startTitle + 2);
        sb.append(apiInfo.getApiType()).append("   ").append(apiInfo.getApiUri()).append("\n");
        setTitle(sb, "服务信息", startTitle + 2);
        sb.append(apiInfo.getApiHeader());
    }

    /**
     * 设置参数说明
     *
     * @param sb             文档信息
     * @param apiParamDescVo 参数说明
     */
    public static void setParamDesc(StringBuilder sb, ApiParamDescVo apiParamDescVo, int startTitle) {
        setTitle(sb, "参数&字段说明", startTitle + 1);
        setTitle(sb, "入参参数", startTitle + 2);
        setNotBodyParamDesc(sb, "入参头参数说明", apiParamDescVo.getInputHeader(), startTitle);
        setNotBodyParamDesc(sb, "入参路径参数说明", apiParamDescVo.getInputPath(), startTitle);
        setNotBodyParamDesc(sb, "入参查询参数说明", apiParamDescVo.getInputQuery(), startTitle);
        setBodyParamDesc(sb, "入参体参数说明", apiParamDescVo.getInputBody(), startTitle);

        setTitle(sb, "返回参数", startTitle + 2);
        setNotBodyParamDesc(sb, "返回头参数说明", apiParamDescVo.getOutputHeader(), startTitle);
        setBodyParamDesc(sb, "返回体参数说明", apiParamDescVo.getOutputBody(), startTitle);
    }

    /**
     * 设置参数示例
     *
     * @param sb              文档信息
     * @param currentParamHis 参数示例
     */
    public static void setParamHis(StringBuilder sb, ApiParamHis currentParamHis, String titleStr, int startTitle) {
        setTitle(sb, titleStr, startTitle + 1);
        setTitle(sb, "入参参数示例", startTitle + 2);
        setInputHis(sb, currentParamHis, startTitle);

        setTitle(sb, "返回参数示例", startTitle + 2);
        setOutputHis(sb, currentParamHis, startTitle);
    }

    public static void setTitle(StringBuilder sb, String title, int titleNo) {
        if (titleNo < 7) {
            for (int i = 0; i < titleNo; i++) {
                sb.append("#");
            }
            sb.append(" ").append(title).append("\n");
        } else {
            sb.append("**").append(title).append("**\n");
        }
    }

    public static String getMarkdownStr(ApiInfoAllVo apiInfoAllVo, int startTitle) {
        StringBuilder sb = new StringBuilder();
        setApiInfo(sb, apiInfoAllVo.getApiInfo(), startTitle);
        setParamDesc(sb, apiInfoAllVo.getApiParamDescVo(), startTitle);

        if (!CollectionUtils.isEmpty(apiInfoAllVo.getApiParamHisList())) {
            for (int i = 0; i < apiInfoAllVo.getApiParamHisList().size(); i++) {
                ApiParamHis apiParamHis = apiInfoAllVo.getApiParamHisList().get(i);
                if (Objects.nonNull(apiParamHis)) {
                    String titleStr = "示例" + i + ": " + apiParamHis.getParamName();
                    setParamHis(sb, apiParamHis, titleStr, startTitle);
                }
            }
        }

        return sb.toString();
    }

    private static void setInputHis(StringBuilder sb, ApiParamHis currentParamHis, int startTitle) {
        setHisStr(sb, "入参头参数示例", currentParamHis.getParamInputHeaderStr(), startTitle);
        setHisStr(sb, "入参路径参数示例", currentParamHis.getParamInputPathStr(), startTitle);
        setHisStr(sb, "入参查询参数示例", currentParamHis.getParamInputQueryStr(), startTitle);
        setHisStr(sb, "入参体参数示例", currentParamHis.getParamInputBodyStr(), startTitle);
    }

    private static void setOutputHis(StringBuilder sb, ApiParamHis currentParamHis, int startTitle) {
        setHisStr(sb, "返回头参数示例", currentParamHis.getParamOutputHeaderStr(), startTitle);
        setHisStr(sb, "返回体参数示例", currentParamHis.getParamOutputBodyStr(), startTitle);
    }

    private static void setHisStr(StringBuilder sb, String title, String paramOutputBodyStr, int startTitle) {
        if (StringUtils.isEmpty(paramOutputBodyStr)) {
            return;
        }
        setTitle(sb, title, startTitle + 3);
        sb.append("```json\n").append(paramOutputBodyStr).append("\n```\n");
    }

    private static void setBodyParamDesc(StringBuilder sb, String title, List<ApiParam> inputBody, int startTitle) {
        if (CollectionUtils.isEmpty(inputBody)) {
            return;
        }
        setTitle(sb, title, startTitle + 3);
        for (ApiParam apiParam : inputBody) {
            if (CollectionUtils.isEmpty(apiParam.getFields())) {
                continue;
            }
            sb.append(apiParam.getTitle()).append("\n");
            setFieldTable(sb, apiParam);
        }
    }

    private static void setNotBodyParamDesc(StringBuilder sb, String title, ApiParam param, int startTitle) {
        if (Objects.isNull(param) || CollectionUtils.isEmpty(param.getFields())) {
            return;
        }
        setTitle(sb, title, startTitle + 3);
        setFieldTable(sb, param);
    }

    private static void setFieldTable(StringBuilder sb, ApiParam param) {
        if (Objects.isNull(param) || CollectionUtils.isEmpty(param.getFields())) {
            return;
        }
        setDesc(sb, param.getParamDesc());
        setTableStart(sb);
        for (ApiParamField field : param.getFields()) {
            setFieldDesc(sb, field);
        }
    }

    private static void setDesc(StringBuilder sb, String paramDesc) {
        if (!SystemConstants.NO_DATA.equals(paramDesc)) {
            sb.append(paramDesc).append("\n");
        }
    }

    private static void setTableStart(StringBuilder sb) {
        for (String title : FIELD_TITLE_STR) {
            sb.append("| ").append(title);
        }
        sb.append("|\n");
        for (String s : FIELD_TITLE_STR) {
            sb.append("| ----- ");
        }
        sb.append("|\n");
    }

    private static void setFieldDesc(StringBuilder sb, ApiParamField field) {
        String filedTypeStr = EntityToWord.ID_AND_NAME_TYPE_MAP.get(field.getFieldTypeId());
        filedTypeStr = StringUtils.isEmpty(filedTypeStr) ? String.valueOf(field.getFieldTypeId()) : filedTypeStr;
        sb.append("| ").append(setFieldMust(field.getFieldName(), field.getFieldMust()))
                .append(" | ").append(setFieldMust(filedTypeStr, field.getFieldMust()))
                .append(" | ").append(setFieldMust(field.getFieldMust(), field.getFieldMust()))
                .append(" | ").append(field.getFieldDesc()).append(" |\n");
    }

    private static String setFieldMust(String fieldName, String fieldMust) {
        if (SystemConstants.STR_YES.equals(fieldMust)) {
            return "**" + fieldName + "**";
        }
        return fieldName;
    }
}
